#include <linux/module.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <rtdm/driver.h>
#include <rtdm/udd.h>
#include <linux/platform_device.h>

#define OMAP_MAX_GPIO		192

#define AM33XX_GPIO0_BASE       0x44E07000
#define AM33XX_GPIO1_BASE       0x4804C000
#define AM33XX_GPIO2_BASE       0x481AC000
#define AM33XX_GPIO3_BASE       0x481AE000

#define GPIO_TO_PIN(bank, gpio)		(32 * (bank) + (gpio))

#define RTDM_SUBCLASS_OMAP_GPIO       0
#define DEVICE_NAME                 "udd_gpio"

MODULE_DESCRIPTION("UDD driver for OMAP3 GPIO");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wsg1100");

static struct udd_device device = {
    .device_name = DEVICE_NAME,
    .device_flags		=	RTDM_NAMED_DEVICE|RTDM_EXCLUSIVE,
    .device_subclass = RTDM_SUBCLASS_OMAP_GPIO,
    .mem_regions[0].name = "gpio0_addr",
    .mem_regions[0].addr = AM33XX_GPIO0_BASE,
    .mem_regions[0].len = 4096,
    .mem_regions[0].type = UDD_MEM_PHYS, 

    .mem_regions[1].name = "gpio1_addr",
    .mem_regions[1].addr = AM33XX_GPIO1_BASE,
    .mem_regions[1].len = 4096,
    .mem_regions[1].type = UDD_MEM_PHYS, 

    .mem_regions[2].name = "gpio2_addr",
    .mem_regions[2].addr = AM33XX_GPIO2_BASE,
    .mem_regions[2].len = 4096,
    .mem_regions[2].type = UDD_MEM_PHYS, 

    .mem_regions[3].name = "gpio3_addr",
    .mem_regions[3].addr = AM33XX_GPIO3_BASE,
    .mem_regions[3].len = 4096,
    .mem_regions[3].type = UDD_MEM_PHYS, 
};
	
static int udd_gpio_probe(struct platform_device *pdev)
{
	dev_info(&pdev->dev, "mem region len: %d\n",device.mem_regions[0].len);
    dev_info(&pdev->dev, "mem region addr: 0x%08lx\n",device.mem_regions[0].addr);
    dev_info(&pdev->dev, "mem region len: %d\n",device.mem_regions[1].len);
    dev_info(&pdev->dev, "mem region addr: 0x%08lx\n",device.mem_regions[1].addr);
    dev_info(&pdev->dev, "mem region len: %d\n",device.mem_regions[2].len);
    dev_info(&pdev->dev, "mem region addr: 0x%08lx\n",device.mem_regions[2].addr);
    dev_info(&pdev->dev, "mem region len: %d\n",device.mem_regions[3].len);
    dev_info(&pdev->dev, "mem region addr: 0x%08lx\n",device.mem_regions[3].addr);

    return udd_register_device (&device);
}

static int udd_gpio_remove(struct platform_device *pdev)
{
	udd_unregister_device (&device);

	return 0;
}


static const struct of_device_id udd_gpio_ids[] = {
	{ .compatible = "ti,omap3-udd-gpio" },
	{},
};

MODULE_DEVICE_TABLE(of, udd_gpio_ids);

static struct platform_driver udd_gpio_platform_driver = {
	.driver = {
		.name		= DEVICE_NAME,
		.of_match_table = udd_gpio_ids,
	},
	.probe			= udd_gpio_probe,
	.remove			= udd_gpio_remove,
};

int __init omap_gpio_init(void)
{
	return platform_driver_register(&udd_gpio_platform_driver);
}

void __exit omap_gpio_exit(void)
{
    return platform_driver_unregister(&udd_gpio_platform_driver);
}

module_init(omap_gpio_init);
module_exit(omap_gpio_exit);


